Completed
Push — master ( aed6fc...c6fbd4 )
by Jeroen De
47:18
created

form_validation.js ➔ isEmptyString   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 1
nc 1
nop 1
1
'use strict';
2
3
var jQuery = require( 'jquery' ),
4
	objectAssign = require( 'object-assign' ),
5
	Promise = require( 'promise' ),
0 ignored issues
show
Comprehensibility introduced by
You are shadowing the built-in type Promise. This makes code hard to read, consider using a different name.
Loading history...
6
	_ = require( 'underscore' ),
7
8
	ValidationStates = {
9
		OK: 'OK',
10
		ERR: 'ERR',
11
		INCOMPLETE: 'INCOMPLETE',
12
		NOT_APPLICABLE: 'NOT_APPLICABLE'
13
	},
14
15
	isEmptyString = function ( value ) {
16
		return value === '';
17
	},
18
19
	DefaultRequiredFieldsForAddressType = {
20
		person: [ 'salutation', 'firstName', 'lastName', 'street', 'postcode', 'city', 'email' ],
21
		firma: [ 'companyName', 'street', 'postcode', 'city', 'email' ],
22
		anonym: []
23
	},
24
25
	/**
26
	 * This function avoids an endless loop on failure.
27
	 * The jQuery fail function returns the xhrObject, which is itself a Promise,
28
	 * which will then be called by the Redux promise_middleware again and again.
29
	 *
30
	 * When IE support is finally ditched and we use jQuery >= 3.0, this wrapper method must be removed.
31
	 *
32
	 * @param jQueryDeferredObject
33
	 * @returns {Promise}
34
	 */
35
	jQueryDeferredToPromise = function ( jQueryDeferredObject ) {
36
		return new Promise( function ( resolve, reject ) {
37
			jQueryDeferredObject.then( resolve, function ( xhrObject, statusCode, statusMessage ) {
38
				reject( statusMessage );
39
			} );
40
		} );
41
	},
42
43
	AddressValidator = {
44
		validationUrl: '',
45
		sendFunction: null,
46
		requiredFields: {},
47
		validate: function ( formValues ) {
48
			var requiredFields = this.getRequiredFieldsForAddressType( formValues.addressType );
49
			if ( this.formValuesHaveEmptyRequiredFields( formValues, requiredFields ) ) {
50
				return { status: ValidationStates.INCOMPLETE };
51
			}
52
			// Don't send anything to server if there are no fields to validate
53
			if ( requiredFields.length === 0 ) {
54
				return { status: ValidationStates.OK };
55
			}
56
57
			return jQueryDeferredToPromise( this.sendFunction( this.validationUrl, formValues, null, 'json' ) );
58
		},
59
		formValuesHaveEmptyRequiredFields: function ( formValues, requiredFields ) {
60
			var objectWithOnlyTheRequiredFields = _.pick( formValues, requiredFields );
61
			return _.find( objectWithOnlyTheRequiredFields, isEmptyString ) !== undefined;
62
		},
63
		getRequiredFieldsForAddressType: function ( addressType ) {
64
			if ( !_.has( this.requiredFields, addressType ) ) {
65
				throw new Error( 'Invalid address type: ' + addressType );
66
			}
67
			return this.requiredFields[ addressType ];
68
		}
69
	},
70
71
	EmailAddressValidator = {
72
		validationUrl: '',
73
		sendFunction: null,
74
		validate: function ( formValues ) {
75
			var postData = {
76
				email: formValues.email
77
			};
78
			return jQueryDeferredToPromise( this.sendFunction( this.validationUrl, postData, null, 'json' ) );
79
		}
80
	},
81
82
	AmountValidator = {
83
		validationUrl: '',
84
		sendFunction: null,
85
		validate: function ( formValues ) {
86
			var postData = {
87
				amount: formValues.amount,
88
				paymentType: formValues.paymentType
89
			};
90
			return jQueryDeferredToPromise( this.sendFunction( this.validationUrl, postData, null, 'json' ) );
91
		}
92
	},
93
94
	FeeValidator = {
95
		validationUrl: '',
96
		sendFunction: null,
97
		validate: function ( formValues ) {
98
			var postData = {
99
				amount: formValues.amount,
100
				paymentIntervalInMonths: formValues.paymentIntervalInMonths,
101
				addressType: formValues.addressType
102
			};
103
			return jQueryDeferredToPromise( this.sendFunction( this.validationUrl, postData, null, 'json' ) );
104
		}
105
	},
106
107
	BankDataValidator = {
108
		validationUrlForSepa: '',
109
		validationUrlForNonSepa: '',
110
		sendFunction: null,
111
		validate: function ( formValues ) {
112
			if ( formValues.paymentType && formValues.paymentType !== 'BEZ' ) {
113
				return {
114
					status: ValidationStates.NOT_APPLICABLE
115
				};
116
			}
117
118
			if ( formValues.debitType === 'sepa' ) {
119
				return this.validateSepa( formValues );
120
			}
121
122
			return this.validateNonSepa( formValues );
123
		},
124
		/**
125
		 * @private
126
		 */
127
		validateSepa: function ( formValues ) {
128
			if ( formValues.iban === '' ) {
129
				return { status: ValidationStates.INCOMPLETE };
130
			}
131
132
			return this.getValidationResultFromApi(
133
				this.validationUrlForSepa,
134
				{
135
					iban: formValues.iban
136
				}
137
			);
138
		},
139
		/**
140
		 * @private
141
		 */
142
		validateNonSepa: function ( formValues ) {
143
			if ( formValues.accountNumber === '' || formValues.bankCode === '' ) {
144
				return { status: ValidationStates.INCOMPLETE };
145
			}
146
147
			return this.getValidationResultFromApi(
148
				this.validationUrlForNonSepa,
149
				{
150
					accountNumber: formValues.accountNumber,
151
					bankCode: formValues.bankCode
152
				}
153
			);
154
		},
155
		/**
156
		 * @private
157
		 */
158
		getValidationResultFromApi: function ( apiUrl, urlArguments ) {
159
			return jQueryDeferredToPromise(
160
				this.sendFunction(
161
					apiUrl,
162
					urlArguments,
163
					null,
164
					'json'
165
				)
166
			);
167
		}
168
	},
169
170
	SepaConfirmationValidator = {
171
		validate: function ( formValues ) {
172
			return formValues.confirmSepa && formValues.confirmShortTerm !== false;
173
		}
174
	},
175
176
	createAddressValidator = function ( validationUrl, requiredFields, sendFunction ) {
177
		return objectAssign( Object.create( AddressValidator ), {
178
			validationUrl: validationUrl,
179
			requiredFields: requiredFields,
180
			sendFunction: sendFunction || jQuery.post
181
		} );
182
	},
183
184
	createEmailAddressValidator = function ( validationUrl, sendFunction ) {
185
		return objectAssign( Object.create( EmailAddressValidator ), {
186
			validationUrl: validationUrl,
187
			sendFunction: sendFunction || jQuery.post
188
		} );
189
	},
190
191
	/**
192
	 *
193
	 * @param {string} validationUrl
194
	 * @param {Function} sendFunction jQuery.post function or equivalent
195
	 * @return {AmountValidator}
196
	 */
197
	createAmountValidator = function ( validationUrl, sendFunction ) {
198
		return objectAssign( Object.create( AmountValidator ), {
199
			validationUrl: validationUrl,
200
			sendFunction: sendFunction || jQuery.post
201
		} );
202
	},
203
204
	createFeeValidator = function ( validationUrl, sendFunction ) {
205
		return objectAssign( Object.create( FeeValidator ), {
206
			validationUrl: validationUrl,
207
			sendFunction: sendFunction || jQuery.post
208
		} );
209
	},
210
211
	createBankDataValidator = function ( validationUrlForSepa, validationUrlForNonSepa, sendFunction ) {
212
		return objectAssign( Object.create( BankDataValidator ), {
213
			validationUrlForSepa: validationUrlForSepa,
214
			validationUrlForNonSepa: validationUrlForNonSepa,
215
			sendFunction: sendFunction || jQuery.get
216
		} );
217
	}
218
	;
219
220
module.exports = {
221
	createAmountValidator: createAmountValidator,
222
	createFeeValidator: createFeeValidator,
223
	createAddressValidator: createAddressValidator,
224
	createEmailAddressValidator: createEmailAddressValidator,
225
	createBankDataValidator: createBankDataValidator,
226
	createSepaConfirmationValidator: function () {
227
		return Object.create( SepaConfirmationValidator );
228
	},
229
	DefaultRequiredFieldsForAddressType: DefaultRequiredFieldsForAddressType,
230
	ValidationStates: ValidationStates
231
};
232